/* NOTICE
 
    Jim - the Java Image Manager, copyright (c) 2005 - 2007 Grant Gardner 
 
    Jim is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Jim is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  
    In addition, as a special exception, you are permitted to link this code
    with the 3rd party libraries required to compile this file and to
    distribute a linked combination including them. You must obey the
    GNU General Public License in all respects for all of the code except for
    those 3rd party libraries that are licenced under terms incompatible with the
    GNU General Public License.  
 
 
 NOTICE */

package au.com.lastweekend.jim.model;

import java.awt.Dimension;
import java.awt.Frame;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;

import au.com.lastweekend.jim.swing.LIFOListModel;

public class JimConfiguration extends Properties {

    private static final String LDIF_FILE = "jim.ldifFile";

    public enum ImageBaseType {
        LDAP, LDIF, NONE

    }

    private static final long serialVersionUID = -4064755235611677330L;

    private static final String JIM_CONFIG_PATH, JIM_USER_HOME;

    private static final Logger LOG = Logger.getLogger(JimConfiguration.class);

    private static final String WIDTH = "width";

    private static final String HEIGHT = "height";

    private static final String FRAME_STATE = "frameState";

    private static final String DEFAULT_FRAME_STATE = Integer.toString(Frame.NORMAL);

    public static final String OPEN_SHEETS = "openSheets";

    private static final String RECENT_MOVE_FOLDERS = "recentMoveFolders";

    private static final int MAX_RECENT_DIRS = 10;

    public static final String ROTATE_BY_ORIENTATION = "RotateByOrientation";

    private static final String IMAGE_CACHE_SIZE = "ImageCacheSize";

    private static final String DEFAULT_CACHE_SIZE = "5";

    private static final String IMAGE_BASE_TYPE = "ImageBaseType";

    private static final String DEFAULT_IMAGE_BASE_TYPE = "BOGUS";

    private static final String LDAP_BIND_DN = "ldapBindDN";

    private static final String DEFAULT_LDAP_BIND_DN = "cn=Manager,dc=lastweekend,dc=com,dc=au";

    private static final String LDAP_BIND_PWD = "ldapBindPwd";

    private static final String DEFAULT_LDAP_BIND_PWD = "jimadmin";

    private static final String LDAP_BIND_URL = "ldapBindURL";

    private static final String DEFAULT_LDAP_BIND_URL = "ldap://localhost:389/ou=jim,dc=lastweekend,dc=com,dc=au";

    private static final String DEFAULT_LDIF_FILE;

    private static final String USE_IMAGE_IO = "useImageIO";

    private static final String SLIDE_SIZE = "slideSize";

    private static final int DEFAULT_SLIDE_SIZE = 100;

    private static final String PERSISTENCE_FILE;

    private LIFOListModel<File> recentMoveFolders;

    private PropertyChangeSupport propertyChangeSupport;

    static {
        //TODO remove this static guff, and inject the configuration into the model.
        JIM_USER_HOME = System.getProperty("jim.user.home", System.getProperty("user.home") + "/.jim");
        JIM_CONFIG_PATH = JIM_USER_HOME + "/jim.conf";

        LOG.info("Reading/Writing configuration in " + JIM_CONFIG_PATH);

        DEFAULT_LDIF_FILE = JIM_USER_HOME + "/jim.ldif";

        PERSISTENCE_FILE = JIM_USER_HOME + "/JimDocking.xml";

    }

    public JimConfiguration() {

        propertyChangeSupport = new PropertyChangeSupport(this);
        load();

    }

    private void load() {

        try {
            InputStream is = new FileInputStream(JIM_CONFIG_PATH);
            load(is);
        } catch (Exception e) {
            LOG.warn("Unable to load properties from " + JIM_CONFIG_PATH);
        }

    }

    public void store() {

        // Save recent moved folders.
        setRecentMoveFolders(recentMoveFolders.getElements());
        try {
            OutputStream os = new FileOutputStream(JIM_CONFIG_PATH);
            store(os, "Saved properties");
        } catch (Exception e) {
            LOG.error("Unable to save properties in " + JIM_CONFIG_PATH, e);
        }

    }

    public Dimension getFrameDimension() {

        int width = Integer.parseInt(getProperty(WIDTH, "800"));
        int height = Integer.parseInt(getProperty(HEIGHT, "600"));
        if (width <= 0)
            width = 800;
        if (height <= 0)
            height = 600;

        return new Dimension(width, height);
    }

    public void setFrameDimension(Dimension size) {

        setProperty(WIDTH, Integer.toString(size.width));
        setProperty(HEIGHT, Integer.toString(size.height));

    }

    public int getFrameState() {

        return Integer.parseInt(getProperty(FRAME_STATE, DEFAULT_FRAME_STATE));
    }

    public void setFrameState(int extendedState) {

        setProperty(FRAME_STATE, Integer.toString(extendedState));

    }

    private void setKeyAsListOfFiles(List<File> listOfFile, String configKey) {

        // I'm going to use a ^ to separate files. Too bad if you have a
        // directory with a ^ in it.
        StringBuffer buffer = new StringBuffer();
        String sep = "";
        for (File file : listOfFile) {
            buffer.append(sep);
            buffer.append(file.getPath());
            sep = "^";
        }
        setProperty(configKey, buffer.toString());
    }

    public List<File> getOpenSheets() {

        return getKeyAsListOfFiles(OPEN_SHEETS);
    }

    private List<File> getKeyAsListOfFiles(String configKey) {

        List<File> result = new ArrayList<File>();
        String fileProperty = getProperty(configKey, "");
        Pattern splitPattern = Pattern.compile("^", Pattern.LITERAL);
        String[] files = splitPattern.split(fileProperty);
        for (int i = 0; i < files.length; i++) {
            result.add(new File(files[i]));
        }
        return result;
    }

    public LIFOListModel<File> getRecentMoveFolders() {

        if (recentMoveFolders == null) {
            recentMoveFolders = new LIFOListModel<File>(MAX_RECENT_DIRS, getKeyAsListOfFiles(RECENT_MOVE_FOLDERS));
        }

        return recentMoveFolders;

    }

    private void setRecentMoveFolders(List<File> folders) {

        setKeyAsListOfFiles(folders, RECENT_MOVE_FOLDERS);

    }

    public boolean isRotateByOrientation() {

        return Boolean.parseBoolean(getProperty(ROTATE_BY_ORIENTATION, "true"));
    }

    public void setRotateByOrientation(boolean b) {

        boolean oldValue = isRotateByOrientation();
        setProperty(ROTATE_BY_ORIENTATION, String.valueOf(b));
        LOG.info("Orientation set to " + b);
        propertyChangeSupport.firePropertyChange(ROTATE_BY_ORIENTATION, oldValue, b);
    }

    public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {

        propertyChangeSupport.addPropertyChangeListener(propertyName, listener);

    }

    public int getImageCacheSize() {

        String cacheProperty = getProperty(IMAGE_CACHE_SIZE, DEFAULT_CACHE_SIZE);
        int cacheSize = Integer.parseInt(cacheProperty);

        if (cacheSize < 1) {
            cacheSize = 1;
        }

        setProperty(IMAGE_CACHE_SIZE, Integer.toString(cacheSize));

        return cacheSize;

    }

    public int getSlideSize() {

        String slideSizeProperty = getProperty(SLIDE_SIZE, Integer.toString(DEFAULT_SLIDE_SIZE));
        int slideSize = Integer.parseInt(slideSizeProperty);
        return slideSize;
    }

    public void setSlideSize(int slideSize) {

        setProperty(SLIDE_SIZE, Integer.toString(slideSize));
    }

    public ImageBaseType getImageBaseType() {

        try {
            return ImageBaseType.valueOf(getProperty(IMAGE_BASE_TYPE, DEFAULT_IMAGE_BASE_TYPE));
        } catch (IllegalArgumentException iae) {
            StringBuffer msg = new StringBuffer("Invalid config for " + IMAGE_BASE_TYPE + ", valid values are - ");
            ImageBaseType[] validValues = ImageBaseType.values();
            for (int i = 0; i < validValues.length; i++) {
                msg.append(validValues[i]);
                msg.append(" ");
            }

            LOG.warn(msg);
            return ImageBaseType.NONE;
        }
    }

    public String getLdapBindDN() {

        return getProperty(LDAP_BIND_DN, DEFAULT_LDAP_BIND_DN);
    }

    public String getLdapBindPwd() {

        return getProperty(LDAP_BIND_PWD, DEFAULT_LDAP_BIND_PWD);
    }

    public String getLdapBindURL() {

        return getProperty(LDAP_BIND_URL, DEFAULT_LDAP_BIND_URL);
    }

    public String getLdifFile() {

        return getProperty(LDIF_FILE, DEFAULT_LDIF_FILE);
    }

    public boolean isImageIO() {

        String useImageIO = getProperty(USE_IMAGE_IO, "false");
        setProperty(USE_IMAGE_IO, useImageIO);
        return Boolean.parseBoolean(useImageIO);

    }

    /**
     * @return
     */
    public String getDockingPersistenceFile() {

        return PERSISTENCE_FILE;
    }

}
